001 /* 002 * Copyright 2006 Stephen McConnell. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package net.dpml.http; 017 018 import java.net.URI; 019 import java.net.URL; 020 import java.util.ArrayList; 021 022 import net.dpml.logging.Logger; 023 024 import net.dpml.metro.PartsManager; 025 import net.dpml.metro.ComponentHandler; 026 import net.dpml.component.Provider; 027 028 import org.mortbay.thread.ThreadPool; 029 import org.mortbay.jetty.Connector; 030 import org.mortbay.jetty.security.UserRealm; 031 import org.mortbay.xml.XmlConfiguration; 032 033 /** 034 * HTTP server implementation. 035 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 036 * @version 0.0.0 037 */ 038 public class Server extends org.mortbay.jetty.Server 039 { 040 /** 041 * Component context through which the server configuration uri may be declared. 042 */ 043 public interface Context 044 { 045 /** 046 * Get the Jetty XML configuration uri. The configuration uri is 047 * used to establish the default server configuration prior to 048 * customization via the server context. If not supplied the server 049 * will be deployed relative to the supplied context. 050 * 051 * @param uri the default uri 052 * @return a uri referencing a Jetty configuration profile 053 */ 054 URI getConfiguration( URI uri ); 055 056 /** 057 * Get the assigned thread pool. If no thread pool is 058 * assigned by the deployment scenario a default pool 059 * will be established using the thread pool assigned in the 060 * component internal parts. 061 * 062 * @param pool the default value 063 * @return the resolved thread pool 064 */ 065 ThreadPool getThreadPool( ThreadPool pool ); 066 } 067 068 /** 069 * Internal parts managemwent interface. 070 */ 071 public interface Parts extends PartsManager 072 { 073 /** 074 * Return the default thread pool. 075 * @return the default thread pool. 076 */ 077 ThreadPool getThreadPool(); 078 079 /** 080 * Return the collection of handlers. For any given request all handlers 081 * in the collection will be supplied with a request irrespective of response 082 * status. 083 * 084 * @return the configured handler collection. 085 */ 086 HandlerCollection getHandlers(); 087 } 088 089 private final Logger m_logger; 090 private final Context m_context; 091 private final ArrayList m_connections = new ArrayList(); 092 093 /** 094 * Creation of a new HTTP server implementation. 095 * @param logger the assigned logging channel 096 * @param context the assigned deployment context 097 * @param parts the parts manager 098 * @exception Exception if an instantiation error occurs 099 */ 100 public Server( Logger logger, Context context, Parts parts ) throws Exception 101 { 102 super(); 103 104 m_logger = logger; 105 m_context = context; 106 107 getLogger().debug( "commencing http server deployment" ); 108 Logger internal = logger.getChildLogger( "jetty" ); 109 internal.debug( "assigning internal jetty logger" ); 110 LoggerAdapter.setRootLogger( internal ); 111 112 Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); 113 URI uri = context.getConfiguration( null ); 114 if( null != uri ) 115 { 116 getLogger().debug( "applying server configuration: " + uri ); 117 URL url = uri.toURL(); 118 XmlConfiguration config = new XmlConfiguration( url ); 119 config.configure( this ); 120 } 121 122 // 123 // setup the thread pool 124 // 125 126 ThreadPool pool = context.getThreadPool( null ); 127 if( null != pool ) 128 { 129 super.setThreadPool( pool ); 130 } 131 else 132 { 133 super.setThreadPool( parts.getThreadPool() ); 134 } 135 136 // 137 // add connectors, realms and handlers 138 // 139 140 addConnectors( parts ); 141 addUserRealms( parts ); 142 HandlerCollection collection = parts.getHandlers(); 143 setHandler( collection ); 144 145 // notify completion of server establishment 146 147 getLogger().debug( "server established" ); 148 } 149 150 private void addConnectors( PartsManager parts ) throws Exception 151 { 152 getLogger().debug( "commencing connector addition" ); 153 ComponentHandler[] handlers = parts.getComponentHandlers( Connector.class ); 154 getLogger().debug( "connector count: " + handlers.length ); 155 for( int i=0; i<handlers.length; i++ ) 156 { 157 ComponentHandler handler = handlers[i]; 158 getLogger().debug( "adding connector: " + handler ); 159 try 160 { 161 Provider provider = handler.getProvider(); 162 Connector ch = (Connector) provider.getValue( false ); 163 m_connections.add( ch ); 164 } 165 catch( Throwable e ) 166 { 167 final String error = 168 "Failed to deploy content handler: " + handler; 169 throw new Exception( error, e ); 170 } 171 } 172 Connector[] connectors = (Connector[]) m_connections.toArray( new Connector[0] ); 173 setConnectors( connectors ); 174 } 175 176 private void addUserRealms( PartsManager parts ) throws Exception 177 { 178 getLogger().debug( "commencing realm addition" ); 179 ArrayList list = new ArrayList(); 180 ComponentHandler[] handlers = parts.getComponentHandlers( UserRealm.class ); 181 for( int i=0; i<handlers.length; i++ ) 182 { 183 ComponentHandler handler = handlers[i]; 184 getLogger().debug( "adding realm: " + handler ); 185 try 186 { 187 Provider provider = handler.getProvider(); 188 org.mortbay.jetty.security.UserRealm ch = 189 (org.mortbay.jetty.security.UserRealm) provider.getValue( false ); 190 list.add( ch ); 191 } 192 catch( Throwable e ) 193 { 194 final String error = 195 "Failed to deploy user realm: " + handler; 196 throw new Exception( error, e ); 197 } 198 } 199 UserRealm[] realms = (UserRealm[]) list.toArray( new UserRealm[0] ); 200 setUserRealms( realms ); 201 } 202 203 private Logger getLogger() 204 { 205 return m_logger; 206 } 207 }